/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once

#include <向量.h>

#include <线性代数/矢量计算.h>
#include <线性代数/矩阵计算.h>


#include "底层绘图/底层绘图框架.h"
#include "S_Object.h"
#include "core/设备内存缓存.h"
#include "core/空间划分/球形八叉树.h"
#include "core/几何计算/vec_array.h"
#include "core/shader_mesh.h"
#include "core/shader_line.h"
#include "core/mesh_container.h"
#include "core/shader_taster_transform.h"

#include "面/几何模型生成.h"



/*typedef struct {
	vec3*	v;
	uint32	num;
}S_VERT;

typedef struct {
	uint32* index;
	uint32	num;
}S_VERTINDEX;*/







enum E_网格数据枚举 {
	e_Mesh_CPU,
	e_Mesh_CUDA,
	e_Mesh_VULKAN
};



typedef enum {
	e_顶点坐标	= 1 << 1,
	e_顶点法线	= 1 << 2,
	e_顶点UV	= 1 << 3,
	e_顶点颜色	= 1 << 4,
	e_顶点权重	= 1 << 5,
}E_顶点标志位;

#define DEF_Vert预设_vn E_顶点标志位::e_顶点坐标| E_顶点标志位::e_顶点法线
#define DEF_Vert预设_vnu E_顶点标志位::e_顶点坐标| E_顶点标志位::e_顶点法线 | E_顶点标志位::e_顶点UV


typedef enum {
	e_坐标 = E_顶点标志位::e_顶点坐标,
	e_坐标_法线 = E_顶点标志位::e_顶点坐标 | E_顶点标志位::e_顶点法线,
	e_坐标_法线_UV = E_顶点标志位::e_顶点坐标 | E_顶点标志位::e_顶点法线 | E_顶点标志位::e_顶点UV,
	e_坐标_法线_UV_颜色,
	e_坐标_UV,
	e_坐标_颜色 = E_顶点标志位::e_顶点坐标 | E_顶点标志位::e_顶点颜色,
	e_坐标_权重,
}E_顶点组合标志;













struct S_Mesh板载缓存 {
	S_板载缓存* m_顶点;
	S_板载缓存* m_法线;
	S_板载缓存* m_颜色;
	S_板载缓存* m_索引;
	//S_板载缓存* m_权重;
	S_板载缓存* m_间接;

	S_板载缓存* m_UV1;
	S_板载缓存* m_UV索引;
	//S_骨骼*		m_骨骼;
	uint32		m_顶点配置Flags;

	S_Mesh板载缓存() : m_顶点(0), m_法线(0), m_颜色(0), m_索引(0), m_间接(0), m_UV1(0), m_顶点配置Flags(0)
	{
	}

	virtual void	f_填充顶点(const std::vector<vec3>& v, S_设备环境& ctx) = 0;
	virtual void	f_填充法线(const std::vector<vec3>& n, S_设备环境& ctx) = 0;
	virtual void	f_填充颜色(const std::vector<ubvec4>& c, S_设备环境& ctx) = 0;
	virtual void	f_填充索引(const std::vector<uint32>& index, S_设备环境& ctx) = 0;

	virtual void	f_填充UV(const std::vector<vec2>& uv1, uint8 纹理层, S_设备环境& ctx) = 0;

};




struct S_Mesh {
	S_设备环境	m_Ctx;

	E_网格数据枚举	m_Tye;
	E_绘制方式		m_网格类型;

	S_GPU内存块索引* m_顶点;
	S_GPU内存块索引* m_UV;
	S_GPU内存块索引* m_UV索引;
	S_GPU内存块索引* m_索引;
	S_GPU内存块索引* m_面;

	S_GPU内存块索引* m_骨骼属性;
	S_GPU内存块索引* m_骨骼权重;

	S_GPU内存块索引* m_间接;
	S_GPU内存块索引  m_网格元素属性;

	S_GPU内存块索引*	m_底层光追加速结构;
	S_GPU内存块索引		m_光追网格GPU地址引用;
	

	S_板载缓存*		m_颜色;
	//S_板载缓存*		m_索引;
	//S_板载缓存*        m_面;
	S_结构对象指针  m_扩展数据;
	S_UI32Array*    m_材质槽ID;
	//S_板载缓存*     m_UV;
	//S_板载缓存*		m_UV2;
	//S_板载缓存*		m_UV索引;
	S_材质*			m_Material;
	S_GPU参数布局	m_GPU参数布局;
	std::set<S_板载缓存*> m_光追材质链接;

	S_Bounding		m_Bound;
	S_Cube			m_包围盒;
	//uint64			m_顶点元素偏移;
	uint32*			m_顶点配置Flags;
	S_MeshDrawProp* m_绘制属性;

	
	//S_板载缓存* m_间接;
	//S_骨骼*		m_骨骼;
	
	S_板载缓存* m_姿态变换;
	//S_板载缓存* m_蒙皮权重;
	//S_板载缓存* m_顶点对应骨骼ID;
	S_板载缓存* m_选中骨骼ID;

	uint32      uvLayerNum;
	uint32      uvLayerOffset;

	uint32 m_间接绘制偏移;
	uint32 m_间接绘制数量;
	
	vec2			m_深度控制;
	float32			m_线宽;
	
	S_Geom          m_几何属性;
	//vec3			m_包围盒Min;
	//vec3			m_包围盒Max;
	bool			m_显示;
	bool			m_是否链接;



	static S_板载缓存* g_顶点v;
	static S_板载缓存* g_顶点vn;
	static S_板载缓存* g_顶点vc;
	static S_板载缓存* g_顶点vnt;
	static S_板载缓存* g_索引;
	static S_板载缓存* g_面;
	static S_板载缓存* g_BLAS;
	static S_板载缓存* g_TLAS;
	static S_板载缓存* g_实例AS;
	static S_板载缓存* g_RtMesh;

	static S_板载缓存* g_骨骼属性;
	static S_板载缓存* g_骨骼权重;
	//static S_板载缓存* g_顶点骨骼;
	

	static S_板载缓存* g_间接;
	static S_板载缓存* g_索引间接;
	static S_板载缓存* g_网格属性;

	S_Mesh(S_Mesh* me=0) : m_Material(0) {
		m_Tye = E_网格数据枚举::e_Mesh_CPU;
		m_顶点配置Flags = nullptr;
		m_线宽          = 1.0;
		m_显示          = true;
		m_是否链接      = false;

		m_包围盒        = { {}, {} };
		m_深度控制      = { 1, 0 };
		m_几何属性      = {};
		

		m_颜色   = nullptr;
		m_顶点   = nullptr;
		m_索引   = nullptr;
		//m_UV     = nullptr;
		m_UV     = {};
		m_UV索引 = {};

		m_网格元素属性 = {};

		m_底层光追加速结构 = nullptr;
		m_光追网格GPU地址引用 = {};

		
		m_间接     = nullptr;
		m_绘制属性 = nullptr;

		//m_骨骼 = nullptr;
		m_姿态变换 = nullptr;
		m_骨骼属性 = nullptr;
		m_骨骼权重 = nullptr;
		//m_顶点对应骨骼ID = nullptr;
		m_选中骨骼ID     = nullptr;
		m_面             = nullptr;
		f_df_init_GPU参数布局(&m_GPU参数布局);


		m_间接绘制偏移 = 0;
		m_间接绘制数量 = 0;

		m_材质槽ID = nullptr;

		m_网格类型 = E_绘制方式::e_三角形;
	}




	virtual void			f_getBounds(Vec3& outMinExtents, Vec3& outMaxExtents) const {}
	virtual S_结构对象指针	f_get顶点() { return 0; };
	virtual S_结构对象指针	f_get颜色() { return 0; };
	virtual S_结构对象指针	f_get法线() { return 0; };
	virtual S_结构对象指针	f_get索引() { return 0; };


	virtual	void f_get顶点(S_结构对象指针 data) {};
	virtual	void f_get法线(S_结构对象指针 data) {};
	virtual	void f_get索引(S_结构对象指针 data) {};

	virtual	void f_get顶点(std::vector<vec3>& vert) const {};
	virtual	void f_get法线(std::vector<vec3>& normal) const {};
	virtual	void f_get索引(std::vector<uint32>& index) const {};
	virtual	void f_get颜色(std::vector<vec4>& index) const {};



	virtual void f_fill顶点(const vec3* xyz, uint32 num) {}
	virtual void f_fill法线(const vec3* normal, uint32 num) {}
	virtual void f_fill索引(const uint32* index, uint32 num) {}
	virtual void f_fillUV(const vec2* index, uint32 num, uint8 纹理层) {}
	virtual void f_fill权重(const float32* w, uint32 num) {}
	virtual void f_fill骨骼ID(const uint32* bid, uint32 num) {}
	virtual void f_fill骨骼属性(const S_骨骼属性& 骨骼属性) {}


	virtual void f_fill法线(const std::vector<vec3>& normal) {}
	//virtual void f_fill索引(const std::vector<uint32>& index) {}
	virtual void f_fill颜色(const std::vector<S_RGBA8UI>& color) {}
	virtual void f_填充顶点数据(const std::vector<S_VN>& data) {}
	virtual void f_填充顶点数据(const std::vector<S_VC>& data) {}
	virtual uint32 f_填充顶点数据(uint16 bitSize, uint64 num, void* data) {return 0;}
	//virtual void f_填充法线数据(uint16 bitSize, uint64 num, void* data) {}
	virtual uint32 f_填充索引数据(uint16 bitSize, uint64 num, void* data) { return 0; }
	virtual uint32 f_fillUV索引数据(uint16 bitSize, uint32 num, const void* data) {return 0;}


	//virtual void f_set顶点(const S_UI32Array* index, const S_Vec3Array* xyz) {}
	//virtual void f_set法线(const S_UI32Array* index, const S_Vec3Array* normal) {}

	//void f_填充间接数据(const std::vector<S_VkDrawIndexedIndirectCommand>& indirect);

	virtual void f_重置顶点数量(uint64 num) {}
	virtual void f_Clear() {}
	virtual void f_Clear索引(){}




	//virtual void f_resize顶点(uint32 num) {}
	virtual void f_计算包围盒() {}







	virtual	uint32		f_get顶点数量() { return 0; }
	virtual uint32		f_get索引数量() { return 0; }


	virtual void		f_AddMesh(const S_Mesh& m) {}

	
	virtual void		f_to板载缓存() {}
	virtual void		f_clear板载缓存(){}
	
	
	void				f_Transform(const C_Mat44& m);
	void				f_创建板载缓存族(E_绘图API engineType = E_绘图API::E_Vulkan);
	vec3				f_拾取(const vec3& s, const vec3& e);


	


	virtual E_序列map	f_map法线() { return { 0, 0 }; };
	virtual E_序列map	f_map颜色() { return { 0, 0 }; };
	virtual E_序列map	f_mapUV(uint8 纹理层 = 0) { return { 0, 0 }; }


	//virtual void			f_unmap顶点() {}
	virtual void			f_upmap法线() {}
	virtual void			f_upmap颜色() {}
	//virtual void			f_unmap索引() {}

	virtual void			f_upmapUV1() {}
	virtual void			f_upmapUV2() {}





	virtual void		f_updateGPU参数布局() {}
	virtual void		f_绘制(S_渲染参数& 渲染参数) {}
	
protected:

private:
	E_绘图API m_板载缓存族;

};






/*typedef struct {
	vec3* m_顶点;
	vec3* m_法线;
	vec3* m_面中心;
	vec3* m_面法线;
	ivec2* m_边索引;
	uint32* m_面索引;
	uint32* m_材质ID;
	S_Mesh* m_GPU网格;
}S_网格插座数据;*/


/*struct S_GL立即模式 : public S_Mesh {
	
	S_GL立即模式(S_设备环境& ctx);


	void glBegin(E_填充模式 模式);
	void glEnd();

	void glVertex(const vec3& v);
	void glColor(const S_RGBA8UI& c);
	void glNormal(const vec3& n);
	void glCoord(const vec2& t);

	void glMatrixPush();
	void glMatrixPop();
	void glClear();


	void f_绘制(S_渲染参数& 渲染参数);

private:
	uint32	m_Mask;
	uint32	m_Count;
	S_设备环境&	m_Ctx;

	S_MeshBuf*	m_当前网格缓存;

	std::vector<S_MeshBuf> m_Data;
};*/

//void f_构建网格板载内存_1(S_设备环境& ctx, S_MeshBuf& data);


int8 f_顶点配置标志(S_Mesh* mesh, E_顶点标志位 type);
//void f_mesh_配置骨骼GPU参数绑定(S_Mesh* mesh);
void f_mesh_创建骨骼(S_Mesh* mesh, S_设备环境& ctx);

void f_mesh_创建颜色缓存(S_Mesh* mesh, S_设备环境& ctx);



